package com.yiboshi.rehrs.job;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.benmanes.caffeine.cache.Cache;
import com.yiboshi.rehrs.config.RehrsSystemConfig;
import com.yiboshi.rehrs.domain.entity.ZhongUser;
import com.yiboshi.rehrs.domain.entity.ZhongUserImage;
import com.yiboshi.rehrs.domain.model.TaskHostInfo;
import com.yiboshi.rehrs.domain.service.IZhongUserImageService;
import com.yiboshi.rehrs.domain.service.IZhongUserService;
import com.yiboshi.rehrs.exception.ZhongException;
import com.yiboshi.rehrs.helper.RedisHelper;
import com.yiboshi.rehrs.helper.RedisLocker;
import com.yiboshi.rehrs.manager.ZhongYouManager;
import com.yiboshi.rehrs.param.CallRecord;
import com.yiboshi.rehrs.util.*;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static io.lettuce.core.pubsub.PubSubOutput.Type.message;

/**
 * @author jack 2025/3/26
 */

@Component
@Slf4j
public class YuyueJob {
    @Autowired
    IZhongUserImageService zhongUserImageService;

    @Autowired
    IZhongUserService zhongUserService;

    @Autowired
    RedisHelper redisHelper;



    @Autowired
    RedisLocker redisLocker;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    ZhongYouManager zhongYouManager;



    Integer status = 1;


    @Scheduled(cron = "* * * * * ?")//0 0 0/1 * * ?
    public void run() {
        if(StrUtils.isBlank(RehrsSystemConfig.getProfile())){
            return;
        }
        LocalDateTime now = LocalDateTime.now();
        int hour = now.getHour();
        int nowMinute = now.getMinute();
        if(hour<2&&nowMinute<1){
            //清理redis
            cleanRedis();
            return;
        }
        TaskHostInfo taskHostInfo = redisHelper.loadTaskHostInfo( true);
        Integer startHour = taskHostInfo.getStartHour();
        Integer endHour = taskHostInfo.getEndHour();
        if(hour<startHour||hour>endHour){
            return;
        }
        String key = taskHostInfo.getKey();
        Integer skipTask = taskHostInfo.getSkipTask();
        if(skipTask==100){
            Cache<String, Object> cache = CacheUtils.builder(300);
            if(cache.getIfPresent("info")==null){
                log.info("{},skipTask:{}%跳出，未开启任务",key, skipTask);
                cache.put("info",1);
            }
            return;
        }
        if(skipTask>0&&AperStringUtils.randomNum(100)<skipTask){
            //0.3概率跳出
            return;
        }




        int minute = now.getMinute();
        if(hour==19&&minute==1){
            //过期通知
            //今天和明天过期的账号通知
            //DingdingUtils.sendMessageByLocal();
            sendVipMessage();
        }
        if(hour>=21||hour<5){
            //cleanRedis();
            return;
        }

        Cache<String, Object> cache = CacheUtils.builder(120);
        String accountListKey = "vip-account";
        List<ZhongUser> zhongUsers = (List<ZhongUser>) cache.getIfPresent(accountListKey);
        if(zhongUsers==null){
            zhongUsers = zhongUserService.autoTaskAccount(status);
            cache.put(accountListKey,zhongUsers);
        }
        if(CollUtil.isEmpty(zhongUsers)){
            log.info("没有需要自动预约的用户");
            return;
        }
        if(RehrsSystemConfig.isDev()){
            log.info("===========开启任务执行=============");
        }

        StopWatch sw = new StopWatch();
        sw.start("yuyuetask");
        String logonTokenKey =CommonUtil.getLogonTokenKey(LocalDate.now());
        //token
        Map<Object, Object> accountTokenMap = stringRedisTemplate.opsForHash().entries(logonTokenKey);

        Set<String> lockListAccountSet = stringRedisTemplate.keys("zyant-lock:loadList:*");
        //lockMap

        Set<String> lockYuyueAccountSet = stringRedisTemplate.keys("zyant-lock:yuyue:*");

       // List<String> needChargeList = new ArrayList<>();
        //List<CompletableFuture<Void>> futures = new ArrayList<>();
        CountDownLatch latch = new CountDownLatch(zhongUsers.size());
        for (ZhongUser zhongUser : zhongUsers) {
            //并发个数
            if(hour==7&&minute<=10){
                if(AperStringUtils.hitNumber(2)){
                    //7点20前随机跳出
                    latch.countDown();
                    continue;
                }
            }

            String token = accountTokenMap==null?null:(String)accountTokenMap.get(zhongUser.getAccount());
            zhongUser.setToken(token);
          /* while(atomicInteger.get()>=current){
                ThreadUtil.sleep(3);
            }
            atomicInteger.incrementAndGet();*/
            ThreadPoolUtils.submitTask(()->{
                try{
                    //StopWatch swOnw = new StopWatch();
                    //swOnw.start("yuyueByAccount"+zhongUser.getAccount());
                    yueyueByAccount(zhongUser,lockListAccountSet,lockYuyueAccountSet);
                    //swOnw.stop();
                    //log.info(swOnw.toString());
                }finally {
                    //atomicInteger.decrementAndGet();
                    latch.countDown(); // 任务完成，减少计数器
                }
            });
           /* while (atomicInteger.get()>0){
                ThreadUtil.sleep(3);
            }*/
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            log.error("等待任务完成时被中断", e);
            Thread.currentThread().interrupt();
        }
        sw.stop();
        if(RehrsSystemConfig.isDev()||sw.getTotalTimeMillis()>2500){
            log.info("======完成一轮任务,耗时{}ms ========",sw.getTotalTimeMillis());
        }

        //过期通知

        //DingdingUtils.sendMessageByLocal();




        //talkTime  时间  随机 30-45秒 之间
        //mobile 就是最新的手机号
        //callTime 当前时间
        //waybillNo 单号
        //这些必填 其他的写死

    }



    private void cleanRedis() {
        LocalDate now = LocalDate.now();
        String before =  DateUtils.dateToStr(now.plusDays(-2),DateUtils.SQL_DATE);
        String key =String.format("z:waybill:zset:%s:*ok",before);
        redisHelper.delByPattern(key);
        key =String.format("z:waybill:zset:%s:*",before);
        redisHelper.delByPattern(key);
        key =String.format("system_monitor:%s:*",before);
        redisHelper.delByPattern(key);

        String logonTokenKey = CommonUtil.getLogonTokenKey(now.plusDays(-1));
        //redisHelper.delByPattern(key);
        stringRedisTemplate.delete(logonTokenKey);
    }

    private void yueyueByAccount(ZhongUser zhongUser,Set<String> lockListAccountSet,Set<String> lockYuyueAccountSet) {
        String account = zhongUser.getAccount();
        //log.info("自动预约任务开始,account {}",account);
        //n-logon-token:2025-05-04
        String logonByFace_key = CommonUtil.getLogonTokenKey(LocalDate.now());
        String token = zhongUser.getToken();
        LocalDateTime now = LocalDateTime.now();
        int hour = now.getHour();
        if(StrUtils.isBlank(token)&&hour<5){
            //5点前不登录 不执行
            return;
        }
        if(StrUtils.isBlank(token)&&hour>=7){
            //logon
            //7点开始自动登录
            if(hour==7){
                int minute = now.getMinute();
                int time = 60-minute;
                if(time>0){
                    if(time>15){
                        time = 15;
                    }
                    if(time<10){
                        time = 5;
                    }
                    boolean success = redisLocker.tryLock("logonByFace", time+AperStringUtils.randomNum(10));
                    if(!success){
                        //逐渐登录
                        return;
                    }
                }

            }

            String face_key = logonByFace_key+":"+account;
            boolean lock = redisLocker.tryLock(face_key, 200+AperStringUtils.randomNum(120));
            if(!lock){
                if (AperStringUtils.hitNumber(50)) {
                    log.error("account:{} redis登录锁定",account);
                }
                return ;
            }
            ZhongUserImage zhongUserImage = zhongUserImageService.getOne(account);
            //zhongUser.setPadId("c08d8c3ff856477d");
            //zhongUserCache.setPadId("A1000012714E12");
            //zhongUser.setAndroidId("c08d8c3ff856477d");
            String image = zhongUserImage.getImage();
            Pair<ZhongUser,String> pair = zhongYouManager.logonByFace(zhongUser, image);
            token = pair.getKey().getToken();
            if(StrUtils.isBlank(token)){
                if(pair.getValue()!=null&&(pair.getValue().contains("用户失效")
                        ||pair.getValue().contains("被锁定")
                        ||pair.getValue().contains("已解约")
                        ||pair.getValue().contains("设备停用")
                        ||pair.getValue().contains("用户不存在")
                        ||pair.getValue().contains("用户已到期"))){
                    //锁定一个小时
                    int seconds = 7200+AperStringUtils.randomNum(3600);
                    if(LocalDateTime.now().getHour()<=10){
                        //seconds = seconds/2;
                    }else if(LocalDateTime.now().getHour()>=15){
                        seconds = seconds*2;
                    }
                    redisLocker.updateLockTime(face_key,seconds);
                }
                stringRedisTemplate.opsForValue().set("logon-fail:"+account,pair.getValue(),30,TimeUnit.MINUTES);
                log.error("logonByFace res token is null msg:{} account:{}",pair.getValue(),account);
                return;
            }
            ThreadPoolUtils.submitTask(()->{
                //更新机构编码
                LambdaUpdateWrapper<ZhongUser> zhongUserLambdaUpdateWrapper = zhongUserService.getUpdateWrapper().eq(ZhongUser::getAccount, zhongUser.getAccount())
                        .set(ZhongUser::getOrgNo, zhongUser.getOrgNo());
                zhongUserService.update(zhongUserLambdaUpdateWrapper);
            });
            stringRedisTemplate.opsForHash().put(logonByFace_key,account,token);
            updateMonitor("faceLogin",account);
        }
        if(StrUtils.isBlank(token)){
            //log.info("token is null,account:{}",account);
            return;
        }
        zhongUser.setToken(token);
        LocalDate today = LocalDate.now();
        //DateUtils.getStartDateTimeWithHMS()
        String key = CommonUtil.waybillRedisListKey(account);

        //加载列表
        try{
            String lockListKey = "zyant-lock:loadList:"+account;
            if(LocalDateTime.now().getHour()<20&&!lockListAccountSet.contains(lockListKey)){
                loadList(zhongUser, key);
            }
        }catch (ZhongException e){
            if(e.getMessage().contains("重新登录")){
                log.info("token过期需要重新登录，{}",zhongUser.getAccount());
                //重新登录
                //删除缓存
                //redisHelper.delSessionUser(zhongUser.getToken(),zhongUser.getAccount(),false);
                stringRedisTemplate.opsForHash().delete(logonByFace_key,account);
                return;
            }else{
                log.error("load list account:{},msg:{}",zhongUser.getAccount(),e.getMessage());
            }
        }catch (Exception e){
            log.error("load list account:{}",zhongUser.getAccount(),e);
        }

        //预约
        try{
            String yuyue_lock_key = "zyant-lock:yuyue:"+account;
            if(!lockYuyueAccountSet.contains(yuyue_lock_key)){
                yuyue(zhongUser,key);
                //yuyueTreatTokenOut(zhongUser, key);
            }

        }catch (ZhongException e){
            if(e.getMessage().contains("重新登录")){
                log.info("token过期需要重新登录，{}",account);
                //重新登录
                //删除缓存
                stringRedisTemplate.opsForHash().delete(logonByFace_key,account);
            }else{
                log.error("yuyue account:{},msg:{}",account,e.getMessage());
            }
        }catch (Exception e){
            log.error("yuyue account:{}",account,e);
        }




    }




    private void loadList(ZhongUser zhongUser, String key) {
        LocalDateTime now = LocalDateTime.now();
        int hour = now.getHour();
        int minute = now.getMinute();
        if(hour==7&&minute<=20){
            //7:20之前
            if(AperStringUtils.hitNumber(2)){
                //随机跳出
                return;
            }

        }
        String account = zhongUser.getAccount();
        String jobKey = getLoadListKey(account) ;
        boolean lockSuccess = redisLocker.tryLock(jobKey, 60+AperStringUtils.randomNum(120));
        if(!lockSuccess){
            return;
        }
        log.info("{},查询运单开始",account);

        String state = "a"; //所有
        int wei = 5;
        if(hour>=7&&hour<=8){
            wei = 2;
        }else if(hour>14){
            wei = 4;
        }
        /*if(hour>16){
            wei = 3;
        }*/
        if(AperStringUtils.hitNumber(wei)){
            //state = "2";
        }
        //state = null;
        JSONArray jsonArray = zhongYouManager.findpdasignWaybillinfoNew(zhongUser,state);
        jsonArray = jsonArray==null?new JSONArray():jsonArray;
        updateMonitor("loadWaybillList",account);

        int time = getLoadListTime(hour, jsonArray, state);
        int randomTime = time+AperStringUtils.randomNum(time);
        log.info("{},查询到运单,state:{}:{}个 , 下次查询时间{}分钟后,time:{}",account,state,jsonArray.size(),randomTime/60,time);
        redisLocker.updateLockTime(jobKey,randomTime);
        if(CollUtil.isEmpty(jsonArray)){
            return;
        }
        Set<ZSetOperations.TypedTuple<String>> typedTuplesAll = stringRedisTemplate.opsForZSet().rangeWithScores(key,0,-1);
        //需要预约的运单
        //Set<ZSetOperations.TypedTuple<String>> typedTuplesAll = stringRedisTemplate.opsForZSet().rangeByScoreWithScores(key, Double.MIN_VALUE, Double.MAX_VALUE);
        Map<String,Double> existMap = new HashMap<>();
        if(CollUtil.isNotEmpty(typedTuplesAll)){
            typedTuplesAll.forEach((t)->{
                String value = t.getValue();
                Double score = t.getScore();
                existMap.put(value,score);
            });
        }

        LocalDateTime today = DateUtils.getStartDateTimeWithHMS(LocalDateTime.now());
        Map<String,String> mobileMap = new HashMap<>();
        Set<ZSetOperations.TypedTuple<String>> accountWaybillNoSet = new HashSet<>();
        jsonArray.forEach(o->{
            JSONObject jsonObjectWaybill = (JSONObject)o;
            String waybillNo = jsonObjectWaybill.getString("waybillNo");
            Double score = existMap.get(waybillNo);
            if(score!=null&&score<0d){
                //分数为负数 说明已经处理
                return;
            }
            //String importScanOrder1 = jsonObjectWaybill.getString("importScanOrder");
            //String substring = importScanOrder1.substring(2);
            Date importRegionDate = jsonObjectWaybill.getDate("importRegionDate");
            LocalDateTime localDateTime = DateUtils.dateToLocalDateTime(importRegionDate);

            if(localDateTime.isBefore(today)){
                return;
            }

            //long importScanOrder = Long.valueOf(substring);
            //20250412083217
            //       1000000

            //stringRedisTemplate.opsForZSet().
            boolean startWith1_8  = isStartWith1_8(waybillNo);
            boolean isLetterStart = Character.isLetter(waybillNo.toLowerCase().charAt(0));
            String manOutCall = jsonObjectWaybill.getString("manOutCall");
            manOutCall = manOutCall==null?"":manOutCall;
            //2503270834460001
            //long youxian = 400000000L;
            //ZSetOperations.TypedTuple<String> typedTuple =
            //妥投时间
            String signFeedbackDate = jsonObjectWaybill.getString("signFeedbackDate");
            if(isLetterStart){
                //字母开头的跳过
                DefaultTypedTuple<String> defaultTypedTuple = new DefaultTypedTuple(waybillNo,-10003d);//字母开头不处理  -10003字母开头不处理
                accountWaybillNoSet.add(defaultTypedTuple);
            }else  if(manOutCall.contains("已电联成功")){

                DefaultTypedTuple<String> defaultTypedTuple = new DefaultTypedTuple(waybillNo,-10002d);//列表已电联  -10000已电联还是约了
                accountWaybillNoSet.add(defaultTypedTuple);
                //stringRedisTemplate.opsForZSet().add(key,waybillNo,);
                return;
            }else  if(StrUtils.isNotBlank(signFeedbackDate)){
                DefaultTypedTuple<String> defaultTypedTuple = new DefaultTypedTuple(waybillNo,-10001d);//-1列表已妥投
                accountWaybillNoSet.add(defaultTypedTuple);

                //stringRedisTemplate.opsForZSet().add(key,waybillNo,);
                return;
            }else{
                //Double score = stringRedisTemplate.opsForZSet().score(key, waybillNo);
                //score = existMap.get(waybillNo);
                if(score==null){
                    //下段时间
                    Long importRegionDateLong = DateUtils.dateTimeToLong(localDateTime, DateUtils.DATE_TIME);
                    //不是1、8开头的 增加一天时间 分数越低 优先级越高
                    if(!startWith1_8){
                        importRegionDateLong = importRegionDateLong+1000000;
                    }
                    String receiverMobile = jsonObjectWaybill.getString("receiverMobile");
                    if(StrUtils.isNotBlank(receiverMobile)&&receiverMobile.length()>=7&&!receiverMobile.contains("*")){
                        mobileMap.put(waybillNo,receiverMobile);
                    }
                    accountWaybillNoSet.add(new DefaultTypedTuple(waybillNo,new Double(importRegionDateLong)));
                    //stringRedisTemplate.opsForZSet().add(key,waybillNo,importScanOrder);
                }else{
                    //log.info("waybillNo:{},score:{}",waybillNo,score);
                }
            }
        });
        if(CollUtil.isNotEmpty(accountWaybillNoSet)){
            stringRedisTemplate.opsForZSet().add(key,accountWaybillNoSet);
        }
        if(CollUtil.isNotEmpty(mobileMap)){
            //手机号码
            String keyMobile =buildAccountBillMobile(account);
            stringRedisTemplate.opsForHash().putAll(keyMobile,mobileMap);
            stringRedisTemplate.expire(keyMobile,20, TimeUnit.HOURS);
        }

    }

    private static boolean isStartWith1_8(String waybillNo) {
        return waybillNo.startsWith("1") || waybillNo.startsWith("8");
    }

    public static String getLoadListKey(String account) {
        return "loadList:"+account;
    }

    //下次加载list的时间xx秒以后
    private static int getLoadListTime(int hour, JSONArray jsonArray, String state) {
        int time = 600;
        if(hour <=7){
            time = 900; //15分钟
            return  time;
        }
        if(jsonArray.size()<=10&& state.equals("a")){
            //一天没有多少单的
            if(hour >=11){
                time = time+150;
            }
            if(hour >=12){
                time = time+300;
            }
            if(hour >=14){
                time = time+300;
            }
            if(hour >=16){
                time = time+300;
            }
            if(hour >=17){
                time = time+3600*3;
            }
            return time;
        }
        if(hour ==8) {
            time = 720; //12分钟
            return  time;
        }
       /* if(hour ==12){
            time = 600;
            return  time;
        }*/

        if(hour ==12||hour ==13){
            time = time+150;
        }
        if(hour >=14){
            time = time+120;
        }
        if(hour >=17){
            time = time+120;
        }
        if(hour >=18){
            time = time+120;
            if(AperStringUtils.hitNumber(2)){
                time = time+120;
            }
        }
        if(hour >=19){
            time = time+900;
        }
        if(hour >=20){
            time = time+900;
        }
        if(hour >=21){
            time = time+3600;
        }
        return time;
    }


    //0没有  1成功 2失败
    public int yuyue( ZhongUser zhongUser,String key){

        //Long startScore = Long.valueOf(DateUtils.toInt(today)+"0000");
        //404 没有单
        //200 没有手机号码
        //-1000

        String account = zhongUser.getAccount();
        //锁定账号
        String user_key = CommonUtil.yuyueRedisKey(account);//"yuyue:"+account;
        int lockTime = 27 + AperStringUtils.randomNum(10);
        boolean lock = redisLocker.tryLock(user_key,lockTime );
        if(!lock){
            return 0;
        }
        Set<ZSetOperations.TypedTuple<String>>  typedTuples = stringRedisTemplate.opsForZSet().rangeByScoreWithScores(key, 0, Long.MAX_VALUE, 0, 2);
        if(CollUtil.isEmpty(typedTuples)){
            return 0;
        }
        List<ZSetOperations.TypedTuple<String>> typedTuplesList = new ArrayList<>(typedTuples);
        //log.info("yuyue account {}, 锁定{}秒",account,lockTime);

        ZSetOperations.TypedTuple<String> typedTuple =  typedTuplesList.get(0);
        String waybillNo = typedTuple.getValue();
        boolean start_1_8 = isStartWith1_8(waybillNo);
        Integer autoTaskType = zhongUser.getAutoTaskType();
        if(!start_1_8&&Objects.equals(autoTaskType,2)){
            //只约1和8
            return 0;
        }
        boolean isStartWithNum = false;
        if(!start_1_8){
           /* if(AperStringUtils.hitNumber(3)){
                //不是1和8 随机跳出 预约速度放慢
                return 0;
            }*/
            isStartWithNum = NumberUtil.isNumber(waybillNo.substring(0,1));
            if(!isStartWithNum){
                stringRedisTemplate.opsForZSet().add(key,waybillNo,-10003d);//-10003字母开头不处理
                return 0;
            }
            lockTime = lockTime+10+AperStringUtils.randomNum(15);
            int hour = LocalDateTime.now().getHour();
            if(hour==9||hour==10||hour==15||hour==16){
                lockTime = lockTime+30;
            }
            redisLocker.updateLockTime(user_key,lockTime );
        }
        Double score = typedTuple.getScore();
        String keyMobile =buildAccountBillMobile(account);
        String mobile = (String)stringRedisTemplate.opsForHash().get(keyMobile,waybillNo);
        boolean isResultOK = false;
        if(StrUtils.isBlank(mobile)){
            //自动预约 查询订单
            JSONObject jsonObject = null;
            try{
                jsonObject = zhongYouManager.queryWaybill(zhongUser, waybillNo);
            }catch (Exception e){
                if(e.getMessage().contains("不存在此邮件号码")){
                    stringRedisTemplate.opsForZSet().add(key,waybillNo,-404);//没有邮件跳过
                }else if(score>10000){//下段第一次错误
                    //stringRedisTemplate.opsForZSet().remove(key,waybillNo);
                    stringRedisTemplate.opsForZSet().add(key,waybillNo,1);//
                }else if(score<5&&score>0){
                    stringRedisTemplate.opsForZSet().add(key,waybillNo,score+1);//
                }else{
                    //stringRedisTemplate.opsForZSet().add(key,waybillNo,-500);//查询邮件报错跳过 重试4次后 -500不再处理
                    stringRedisTemplate.opsForZSet().remove(key,waybillNo);
                }
               /* ZhongException zhongException = (ZhongException)e;
                if("B00001".equals(zhongException.getCode())){

                }*/
                log.error("queryWaybill account:{},waybillNo:{},error:{}",account,waybillNo,e.getMessage());
                redisLocker.updateLockTime(user_key,10+AperStringUtils.randomNum(10));
                return 0;
            }

            if(jsonObject==null){
                redisLocker.updateLockTime(user_key,5+AperStringUtils.randomNum(5));
                return 0;
            }
            String phoneResults = jsonObject.getString("phoneResults");

            isResultOK = StrUtils.isNotBlank(phoneResults)&&phoneResults.contains("已电联");
            if(isResultOK){
                Date callTime = jsonObject.getDate("callTime");
                if(callTime!=null){
                    LocalDateTime localDate = DateUtils.dateToLocalDateTime(callTime);
                    if(localDate.isAfter(LocalDate.now().atStartOfDay())){
                        //今天预约过
                        stringRedisTemplate.opsForZSet().add(key,waybillNo,-20000d);//已电联不处理了
                        log.info("queryWaybill已电联 account:{},waybillNo:{}",account,waybillNo);
                        boolean success = redisLocker.tryLock("loadList:again"+account, 600);
                        if(success){
                            //数据不一致 获取一次列表
                            log.info("数据不一致,重新获取一次列表,{}",account);
                            redisLocker.updateLockTime(getLoadListKey(account),30);
                        }
                        return 0 ;
                    }
                }
            }
            mobile = jsonObject.getString("mobile");
            if(StrUtils.isBlank(mobile)){
                mobile = "11111111111";
                log.info("account:{},waybillNo:{},原来手机号为空,更新新手机号:{}",account,waybillNo,mobile);
                zhongYouManager.updatePhone(zhongUser,waybillNo,mobile);
            }
            String waybillPhoneKey = buildAccountBillMobile(account);
            stringRedisTemplate.opsForHash().put(waybillPhoneKey,waybillNo,mobile);
        }
        String newPhone = "";
        if(StrUtils.isBlank(mobile)){
            //空号不约 移除后 list加载后会重试
            mobile = "11111111111";
            log.info("account:{},waybillNo:{},原来手机号为空,直接用:{} 预约",account,waybillNo,mobile);
        }
        newPhone = mobile;
        if(newPhone.endsWith("#")){//手机号不能带# 重要
            newPhone = newPhone.substring(0,mobile.length()-1);
        }
        //talkTime  时间  随机 30-45秒 之间
        //mobile 就是最新的手机号
        //callTime 当前时间
        //waybillNo 单号
        CallRecord callFile = new CallRecord();
        int time = 27+AperStringUtils.randomNum(26);
        callFile.setCallTime(DateUtils.dateTimeToStr(LocalDateTime.now(),DateUtils.SQL_TIME));
        callFile.setTalkTime(time+"秒");//大象没有秒 金蛇有秒 zy有秒
        callFile.setWaybillNo(waybillNo);
        callFile.setMobile(newPhone);
        //callFile.setTypeFlag("1");
        callFile.setInFlag("3");
        if(newPhone.length()>12){
            callFile.setWhetherAllowRecording("1");
        }else{
            callFile.setWhetherAllowRecording("0");
        }
        callFile.setIsConnect("1");

         //大象
        //talkTime=28&isConnect=1&mobile=17834568739-3816&returnCable=&projectId=&whetherAllowRecording=0&callTime=2025-04-01%2016:01:04&waybillNo=8433271675311&inFlag=3&oriCsInfo=
        //{"talkTime":"28秒","isConnect":"1","mobile":"17834568739-3816","returnCable":"","projectId":"","whetherAllowRecording":"0","callTime":"2025-04-01 16:01:04","waybillNo":"8433271675311","inFlag":"3","oriCsInfo":""}
        //以上是大象
        //{"talkTime":"29秒","isConnect":"1","mobile":"17895053993-1141","returnCable":"","projectId":"","whetherAllowRecording":"0","callTime":"2025-03-25 18:18:59","waybillNo":"1311616962530","inFlag":"3","oriCsInfo":""}

        //zhongyou:talkTime=2%E7%A7%92&isConnect=0&mobile=15051666861&oriCsInfo=&fileMd5=&whetherAllowRecording=1&inFlag=3&typeFlag=1&returnCable=0&projectId=&callTime=2025-04-01%2016%3A51%3A34&waybillNo=9460090604841

        boolean success = zhongYouManager.newCallAndFile(zhongUser, callFile);
       // if(){}
        //大于2000为正常未预约 0-2000是失败次数
        if(success){
            //预约成功
            updateMonitor("yuyue",account);
            double new_score =isResultOK?-20001d:(score*-1); //-20000已经电联还是预约
            if(new_score==0){
                new_score = -1d;
            }
            stringRedisTemplate.opsForZSet().add(key,waybillNo,new_score);
            LocalDateTime now = LocalDateTime.now();
            //yyyyMMddHHmmss
            String timeNowStr = DateUtils.dateTimeToStr(now, DateUtils.DATE_TIME);
            Double scoreOkTime = Double.valueOf(timeNowStr);
            String key_ok = key.replaceAll(account,"ok_"+account);
            stringRedisTemplate.opsForZSet().add(key_ok,waybillNo,scoreOkTime);
        }else{
            double v = score.doubleValue();
            if(v>10000){
                v=1;
            }else{
                v++;
            }
            if(v==0){
                v=1;
            }
            stringRedisTemplate.opsForZSet().add(key,waybillNo,v);
            if(v>4){
                stringRedisTemplate.opsForZSet().remove(key,waybillNo);
                //redisLocker.updateLockTime(user_key,(i-2)*60+AperStringUtils.randomNum(30));
            }
            redisLocker.updateLockTime(user_key,5+AperStringUtils.randomNum(5));
        }
        if(typedTuplesList.size()==2){
            ZSetOperations.TypedTuple<String> stringTypedTuple = typedTuplesList.get(1);
            String value = stringTypedTuple.getValue();
            if(value.startsWith("1")||value.startsWith("8")){
                //list加载可以推迟
                redisLocker.compareAndAddLockTime(getLoadListKey(account), 80+AperStringUtils.randomNum(30));
            }
        }
        return success?1:2;
    }
String monitor_key = "system_monitor";
    private void updateMonitor(String value,String account) {
        LocalDateTime now = LocalDateTime.now();
        String s = DateUtils.dateTimeToStr(now, DateUtils.SQL_DATE);
        String time = DateUtils.dateTimeToStr(now, DateUtils.SQL_TIME);
        String total_key = monitor_key+":"+ s+":total";
        stringRedisTemplate.opsForHash().put(total_key,value+"Time",time);
        Long increment = stringRedisTemplate.opsForHash().increment(total_key, value + "Count", 1);
        if(value.contains("yuyue")&&increment==1){
            DingdingUtils.sendMessageByLocal(RehrsSystemConfig.getProfile()+"\n"+now+",完成第一个预约,"+account,"");
        }

        String account_key = monitor_key+":"+ s+":"+account;
        stringRedisTemplate.opsForHash().put(account_key,value+"Time",time);
        stringRedisTemplate.opsForHash().increment(account_key,value+"Count",1);
    }


    public static String generatePhoneNumber(String template){
        if(StrUtils.isBlank(template)){
            return "135"+AperStringUtils.getRandomNumString(8);
        }


        boolean endWith = template.endsWith("#");
        if(endWith){
            template = template.substring(0,template.length()-1);
        }
        if(!template.contains("*")){

        }
        return template;

       /* // 替换中间的 * 为随机数字
        String newCode = replaceAsterisks(template.replaceAll("#",""));
        if(!newCode.startsWith("1")){
            newCode = "1"+newCode;
        }
        int indexOf = newCode.indexOf("-");
        String last = "";
        if(indexOf>0){
            last = newCode.substring(indexOf);
            newCode = newCode.substring(0,indexOf);
        }
        if(newCode.length()>11){
            return newCode.replaceAll("_","")+last;
        }
        int len = 12-newCode.length();
        String randomNumString = AperStringUtils.getRandomNumString(len);
        newCode = newCode.replaceAll("_",randomNumString)+last;
        *//*if(endWith){
            newCode = newCode+"#";
        }*//*
        return newCode;*/


    }
    /*手机号处理逻辑
    ***********
*******6868
137****7032
172****9681-6319
172****9681-6319#
转*填充随机数字 转成1开头的11位手机号  并修改
-6319、-6319#  这样的后缀（分机号）需要保留

17289499681-6319 直接使用
17289499681-6319# 去掉#后直接使用

**21***2318
***2424
13******
其他的（包括长度不够的）直接修改1开头的11位的手机号，有数字开头和结尾的保留数字
     */

    /**
     * 使用正则表达式替换字符串中的连续 * 符号为一个 _
     *
     * @param input 输入的字符串，例如 "1***8173"
     * @return 替换后的字符串
     */
    public static String replaceAsterisks(String input) {
        if (input == null || input.isEmpty()) {
            return input;
        }

        // 使用正则表达式替换连续 * 为一个 _
        return input.replaceAll("\\*+", "_");
    }

    public static void main(String[] args) {
        int a = (5-1)*6+3;
        System.out.println(a);
    }

    private void sendVipMessage() {
        boolean success= redisLocker.tryLock("O:SendVipOutMessage", 7200);
        if(!success){
            return;
        }
        String agentAccount = "2153011500166";
        List<ZhongUser> zhongUsers = zhongUserService.todayOutVip(1,agentAccount);
        if(CollUtil.isEmpty(zhongUsers)){
            return;
        }
        LocalDate today = LocalDate.now();
        LocalDate tomorrow = LocalDate.now().plusDays(1);
        LocalDateTime tomorrowO =tomorrow.atStartOfDay();
        StringBuilder todayOut = new StringBuilder(today+"到期用户");
        StringBuilder tomorrowOut =new StringBuilder(tomorrow+"到期用户");
        for (ZhongUser zhongUser : zhongUsers) {
            String account = zhongUser.getAccount();
            //String telephone = zhongUser.getTelephone();
            LocalDateTime vipExpDate = zhongUser.getVipExpDate();
            String msg =  ("\n"+account);
            if(vipExpDate.isAfter(tomorrowO)){
                tomorrowOut.append(msg);
            }else{
                todayOut.append(msg);
            }
        }
        StringBuilder message = new StringBuilder();
        if(todayOut.length()>15){
            message.append(todayOut);
            message.append("\n");
        }
        if(tomorrowOut.length()>15){
            message.append(tomorrowOut);
        }
        ZhongUser zhongUserAgent = zhongUserService.one(agentAccount);
        DingdingUtils.sendMessageByLocal(message.toString(),zhongUserAgent.getTelephone());
    }




    public static String buildAccountBillMobile(String account){
       return  "waybillNo-hash:"+LocalDate.now()+":"+account;
    }
}
